#!/opt/local/bin/python
'''
Created on Apr 11, 2012

@author: Johnathon
'''
from LineValues import X, Zero, One
from Optimizer import simArgs, optimize3, allLinesComparator, \
    gateInputOutputComparator, gateInputOutputAsymmetricComparator, \
    gateOutputComparator, hammingDistanceComparator, setSimArgs
from parse import parse
from podemplus import podem
from random import shuffle, choice
from timeit import Timer
from util import collapseFaults
import util


#filename = "c17"
#filename = "c432"
#filename = "c499"
#filename = "c2670"
filename = "c3540"
#filename = "c880"
#filename = "c1908"

dataIn = None
comparator = None
simArguments = None
timerOutput = None
optimizer = optimize3

def main():
    f = "ISCAS85/" + filename + ".bench"
    pInputs, pOutputs, lines, gates = parse(f)
    print "parse done"
    collapsedFaults = collapseFaults(gates, lines)
    totalNumFaults = len(collapsedFaults)
    tests = []

    print "fault collapser done"
    for equivClass in collapsedFaults:
        testsForClass = []
        for fault in equivClass:
            if isinstance(fault[0], list):
                f1 = fault[0][0]
                f2 = fault[1]
            else:
                f1 = fault[0]
                f2 = fault[1]
            test = podem(f1, f2, pInputs, pOutputs, lines, gates)
            if test is not None and test not in testsForClass:
                testsForClass.append(test)
        if testsForClass:
            tests.append(testsForClass)
    print "hello ladies"
    simArguments = (pInputs, pOutputs, lines, gates)
    
    print "Stats for %s" % filename
    print "Num lines: %s" % len([l for level in lines for l in level])
    print "Num tests: %s" % len(tests)
    print "Total Collapsed Faults: %s" % totalNumFaults
    print "Fault Coverage: %s" % (len(tests) * 100.0 / totalNumFaults,)
    
    print ""
    
    #randomOrdering
    rNums = randomOrdering(tests, simArguments)
    
    print ""
        
    #hammingDistanceComparator
    hammingDistance(tests, simArguments, rNums)
    
    print ""

    #Gate Output
#    gateOutput(tests, simArguments, rNums)
    
    print ""
    
    #GateInputsOutputs
#    gateInputOutput(tests, simArguments, rNums)
    
    print ""
    
    #GateInputOutputAsymetric
#    gateInputOutputAsymmetric(tests, simArguments, rNums)
    
    print ""
    
    #allLines
    allLines(tests, simArguments, rNums)
  
    print ""
  
def randomOrdering(tests, simArguments):
    setSimArgs(simArguments)
    print "Random Ordering:"
    s = [choice(i) for i in tests]
    selectFromEquivClass = []
    for vector in s:
        v = vector[:]
        for i in range(0, len(vector)):
            if vector[i] is X:
                v[i] = choice([Zero, One])
        selectFromEquivClass.append(v)
    shuffle(selectFromEquivClass)
    distance = 0
    for i in range(0, len(selectFromEquivClass)-1):
        distance += allLinesComparator(selectFromEquivClass[i], [selectFromEquivClass[i+1]])[0]
    print "Total: %s" % distance
    print "Average: %s" % (distance / (len(selectFromEquivClass)-1),)
    return (float(distance), float(distance / (len(selectFromEquivClass)-1)))
    
def allLines(tests, simArguments, r):
    print "All Lines:"
    comparator = allLinesComparator
    dataIn = tests
    timerOutput = optimizer(dataIn, comparator, simArguments)
#    t = makeTimer()
#    seconds = t.timeit(1)
#    print ""
#    print "All Lines:"
#    print "%s seconds" % seconds
    distance = 0
    for i in range(0, len(timerOutput)-1):
        distance += allLinesComparator(timerOutput[i], [timerOutput[i+1]])[0]
    print "Total: %s %0.2f%%" % (distance, (r[0] - distance) / r[0] * 100)
    print "Average: %s %0.2f%%" % (distance / (len(timerOutput)-1), ((r[1] - distance / (len(timerOutput)-1)) / r[1]) * 100)
 
    
def gateInputOutputAsymmetric(tests, simArguments, r):
    print "Gate Input Output Asymmetric"
    comparator = gateInputOutputAsymmetricComparator
    dataIn = tests
    timerOutput = optimizer(dataIn, comparator, simArguments)
#    t = makeTimer()
#    seconds = t.timeit(1)
#    print ""
#    print "Gate Input & Output Asymmetric:"
#    print "%s seconds" % seconds
    distance = 0
    for i in range(0, len(timerOutput)-1):
        distance += allLinesComparator(timerOutput[i], [timerOutput[i+1]])[0]
    print "Total: %s %0.2f%%" % (distance, (r[0] - distance) / r[0] * 100)
    print "Average: %s %0.2f%%" % (distance / (len(timerOutput)-1), ((r[1] - distance / (len(timerOutput)-1)) / r[1]) * 100)
 
    
def gateInputOutput(tests, simArguments, r):
    print "Gate Input Output"
    comparator = gateInputOutputComparator
    dataIn = tests
    timerOutput = optimizer(dataIn, comparator, simArguments)
#    t = makeTimer()
#    seconds = t.timeit(1)
#    print ""
#    print "Gate Input & Output:"
#    print "%s seconds" % seconds
    distance = 0
    for i in range(0, len(timerOutput)-1):
        distance += allLinesComparator(timerOutput[i], [timerOutput[i+1]])[0]
    print "Total: %s %0.2f%%" % (distance, (r[0] - distance) / r[0] * 100)
    print "Average: %s %0.2f%%" % (distance / (len(timerOutput)-1), ((r[1] - distance / (len(timerOutput)-1)) / r[1]) * 100)
 
    
def gateOutput(tests, simArguments, r):
    print "Gate Output"
    comparator = gateOutputComparator
    dataIn = tests
    timerOutput = optimizer(dataIn, comparator, simArguments)
    print "done"
#    t = makeTimer()
#    seconds = t.timeit(1)
#    print ""
#    print "Gate Output:"
#    print "%s seconds" % seconds
    distance = 0
    for i in range(0, len(timerOutput)-1):
        distance += allLinesComparator(timerOutput[i], [timerOutput[i+1]])[0]
    print "Total: %s %0.2f%%" % (distance, (r[0] - distance) / r[0] * 100)
    print "Average: %s %0.2f%%" % (distance / (len(timerOutput)-1), ((r[1] - distance / (len(timerOutput)-1)) / r[1]) * 100)

    
def hammingDistance(tests, simArguments, r):
    print "Hamming Distance"
    comparator = hammingDistanceComparator
    dataIn = tests
    util.printListOfLineValues(tests)
    timerOutput = optimizer(dataIn, comparator, simArguments)
#    t = makeTimer()
#    seconds = t.timeit(1)
#    print ""
#    print "Hamming Distance:"
#    print "%s seconds" % seconds
    distance = 0
    for i in range(0, len(timerOutput)-1):
        distance += allLinesComparator(timerOutput[i], [timerOutput[i+1]])[0]
    print "Total: %s %0.2f%%" % (distance, (r[0] - distance) / r[0] * 100)
    print "Average: %s %0.2f%%" % (distance / (len(timerOutput)-1), ((r[1] - distance / (len(timerOutput)-1)) / r[1]) * 100)
    
    
def makeTimer():
    return Timer("timerOutput = optimizer(dataIn, comparator, simArguments)", "from __main__ import dataIn, comparator, simArguments, timerOutput, optimizer")

if __name__ == '__main__':
    main()